<!--
 * @Author: MarioGo
 * @Date: 2021-11-07 16:40:47
 * @LastEditTime: 2021-11-11 15:07:14
 * @LastEditors: MarioGo
 * @Description: 文件描述
 * @FilePath: /zheye/src/components/ValidateInput.vue
 * 可以输入预定的版权声明、个性签名、空行等
-->
<template>
  <div class="validate-input-container pb-3">
    <input
      v-if="tag !== 'textarea'"
      class="form-control"
      :class="{ 'is-invalid': inputRef.error }"
      @blur="validateInput"
      v-model="inputRef.val"
      v-bind="$attrs"
    />
    <textarea
      v-else
      class="form-control"
      :class="{ 'is-invalid': inputRef.error }"
      @blur="validateInput"
      v-model="inputRef.val"
      v-bind="$attrs"
    >
    </textarea>
    <span v-if="inputRef.error" class="invalid-feedback">{{ inputRef.message }}</span>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType, reactive, onMounted } from 'vue';
import { emitter } from '../components/ValidateForm.vue';
// 邮箱正则表达式
const emailReg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
// 校验规则
interface RuleProp {
  type: 'required' | 'email' | 'range' | 'custom';
  message?: string;
  validator?: () => boolean; // custom: 自定义，validator：自定义函数
  min?: { length: number; message: string };
  max?: { length: number; message: string };
}
export type RulesProp = RuleProp[];
export type TagType = 'input' | 'textarea';

export default defineComponent({
  name: 'validateInput',
  props: {
    rules: Array as PropType<RulesProp>,
    modelValue: String,
    tag: {
      type: String as PropType<TagType>,
      default: 'input',
    },
  },
  inheritAttrs: false, //关闭父组件上的atts属性添加 写在组件内部
  setup(props, context) {
    // 自定义ref
    const inputRef = reactive({
      val: props.modelValue || '',
      error: false, //默认错误提示 关闭
      message: '',
      allValidate: false, //完成验证通过
    });
    //更新modelvalue  告诉父级
    const updateValue = (e: KeyboardEvent): void => {
      const targetValue = (e.target as HTMLInputElement).value;
      inputRef.val = targetValue;
      context.emit('update:modelValue', targetValue);
    };

    const clearValueInput = (): void => {
      inputRef.val = '';
      inputRef.error = false;
      inputRef.allValidate = false;
      context.emit('update:modelValue', '');
    };

    const validateInput = (): boolean => {
      if (props.rules) {
        const allPassed = props.rules.every((rule) => {
          let passed = true;
          inputRef.message = rule.message || '';
          switch (rule.type) {
            case 'required':
              passed = inputRef.val.trim() !== '';
              break;
            case 'email':
              passed = emailReg.test(inputRef.val);
              break;
            case 'custom':
              passed = rule.validator ? rule.validator() : true;
              break;
            default:
              break;
          }
          return passed;
        });
        inputRef.error = !allPassed;
        //每次验证完毕看看是否通过验证
        inputRef.allValidate = !inputRef.error;
        return inputRef.allValidate;
      }
      return true;
    };

    onMounted(() => {
      //传送验证方法过去
      emitter.emit('form-item-created', validateInput);
      //传送清空方法过去
      emitter.emit('form-item-clear', clearValueInput);
    });
    return {
      inputRef,
      validateInput,
      updateValue,
    };
  },
});
</script>

<style scoped></style>
